#include <iostream>
#include <vector>
// os
#include <unistd.h>
#include <pthread.h>

std::string ToHex(size_t tid)
{
    char buffer[1024] = {'\0'};
    snprintf(buffer, sizeof(buffer), "0x%lx", tid);
    return buffer;
}

class ThreadData
{
public:
    char name[64];
    int num;
};
void *threadRun(void *argments)
{
    // int cnt = 10;
    // while (cnt)
    // {
    //     std::cout << "new thread tid:" << ToHex(pthread_self()) << ", cnt:" << cnt << std::endl; // pthread_self()返回当前线程的tid
    //     cnt--;
    //     sleep(1);
    // }

    //pthread_detach(pthread_self());//分离指定线程，使它不用被父等待

    // return (void *)111;
    //return argments;s
    pthread_exit(argments);
    //pthread_cancel(pthread_self());
    sleep(2);
    return argments;
}
int main()
{
    std::vector<pthread_t> tids;//存放多线程的tid
    std::vector<ThreadData*> ptds;//存放多线程的（在堆上开辟的）参数对象地址；方便最后统一释放/内存管理
    // 创建多线程
    for (size_t i = 1; i <= 10; i++)
    {
        ThreadData *td = new ThreadData; // 整个对象都是在堆上创建的，给每个线程一块堆空间
        snprintf(td->name, sizeof(td->name), "thread-%d", (int)i);
        td->num = i;
        pthread_t tid;
        int n = pthread_create(&tid, nullptr, threadRun, static_cast<void *>(td));
        if (n != 0)
        {
            std::cerr << "pthread_create fail" << std::endl;
            //delete td; // 创建失败时，删除td
        }
        std::cout << "thread-" << i << " success" << std::endl;
        tids.emplace_back(tid);
    }

    // 等待多线程
    for (auto tid : tids)
    {
        void *result = nullptr;
        int n = pthread_join(tid, &result);
        if (n == 0)
        {
            std::cerr << "pthread_join success, result_name: " << ((ThreadData *)result)->name << std::endl; 
            //std::cerr << "pthread_join success, result_name: " << (long long int)result << std::endl;// 64位os指针8字节->4字节int，会精度丢失
        }
        //delete (ThreadData *)result; // 成功/失败等待线程时，删除td
    }
    ///////////////更好的方法： 引入 std::vector<ThreadData*> 来存储创建的线程数据指针，以确保即使有线程创建失败时也能正确清理。///////////////////////////
    for (auto e : ptds)
    {
        delete e;
    }
    return 0;
}